«A web application is application software that is accessed using a web browser. Web applications are delivered on the World Wide Web to users with an active network connection» - (Wikipedia)
1library(shiny)2ui <-fluidPage()3server <-function(input, output) {}4shinyApp(ui = ui, server = server)
1
Scripting (load packages, data, …)
2
Front end, to define the user interface
3
Back end, to define the server logic
4
Simply run the application
User Interface
Inputs1: functions use to insert input controls into your UI specification
inputId argument: identifier to connect the front end with the back end (e.g. if inputId = 'name', the server function will access it with input$name)
label argument: title of your input in the user interface
ui <-fluidPage(numericInput(inputId ="num", label ="Number one", value =0, min =0, max =100))
User Interface
Outputs1: functions use to insert placeholders that are later filled by the server function
outputId argument: identifier to connect the front end with the back end (e.g. if outputId = 'plot', the server function will update it with output$plot)
Each output function on the front end is coupled with a render function in the back end2.
«The key idea of reactive programming is to specify a graph of dependencies so that when an input changes, all related outputs are automatically updated»1
Server Logic
the server() function
take three parameters: input, output and session
since you never call the server() function yourself, you’ll never create these objects yourself
Server Logic
the input argument
list-like object that contains all the input data sent from the user interface
To read from an input, you must be in a reactive context created by a function like renderText()
ui <-fluidPage(numericInput(inputId ="count", label ="Number of values", value =100))server <-function(input, output, session) {message("The value of input$count is ", input$count)}shinyApp(ui, server)#> Error: Can't access reactive value 'count' outside of reactive consumer.#> ℹ Do you need to wrap inside reactive() or observer()?
Server Logic
the input argument
list-like object that contains all the input data sent from the user interface
To read from an input, you must be in a reactive context created by a function like renderText()
ui <-fluidPage(numericInput(inputId ="count", label ="Number of values", value =100),textOutput(outputId ="message"))server <-function(input, output, session) { output$message("The value of input$count is ", input$count)}shinyApp(ui, server)
Server Logic
the output argument
it’s also a list-like object named according to the output ID
it’s used for sending output instead of receiving input
always use the output object in concert with a render() function
Fill the ####### TO BE COMPLETED ######## sections
Run it
# load packageslibrary(shiny)library(dplyr)library(ggplot2)# load datadata_tdr =readRDS("../export/data_tdr.rds")# define UI for the applicationui <-fluidPage(# # application title# titlePanel("TDR Data"),## # sidebar layout = sidebar panel + main panel# sidebarLayout(## # sidebar panel = sliderInput + radioButtons + checkboxGroupInput# sidebarPanel(####### TO BE COMPLETED ######### sliderInput to choose the number of divessliderInput(...),################################# radioButtons to decide the color coderadioButtons(inputId ="color_code",label ="Color code:",choices =c("Yes", "No"),selected =c("No")),# checkboxGroupInput to select dive typescheckboxGroupInput(inputId ="dive_type", label ="Dive types:", choices =unique(data_tdr$dive_type),selected =unique(data_tdr$dive_type)),# ),# mainPanel = plotOutput# mainPanel(# plotOutput to display main_plotplotOutput(outputId ="main_plot")# )# ))# define server logic required to draw the plotserver <-function(input, output) {# store the plot output$main_plot <-renderPlot({# from data_tdr data_tdr %>%# filter on the number of dives from the sliderInput in the uifilter(dive_number <= input$nb_dives) %>%####### TO BE COMPLETED ######### filter on the dive type from the checkboxGroupInput in the ui################################# initiate a plotggplot(aes(x = datetime, y = depth,group = dive_number))+# which going to be a geom_path = line plotgeom_path(# if color_code == Yesmapping =if(input$color_code =="Yes"){# then use dive_type as color_codeaes(col = dive_type) } ) # +# ### everything below is optional #### # tweak y axis# scale_y_reverse(# # a proper name# name = "Depth (m)",# # fix the limits, note: use rev because we reversed the y axis# limits = rev(range(data_tdr$depth))) +# # tweak x axis# scale_x_datetime(# # a proper name# name = "Time",# # ticks frequency# date_breaks = "20 mins",# # format of labels# date_labels = "%H:%M",# # position# position = "top",# # fix the limits# limits = range(data_tdr$datetime)) +# # tweak color# scale_color_manual(# # fix color for each dive type# values = c(Forage = "#00AFBB", # Transit = "#E7B800", # Drift = "#FC4E07")) +# # rename title of the legend# labs(col = "Dive Type") +# # choose a theme# theme_minimal() +# # and tweak it# theme(# # legend position# legend.position = "bottom",# # add arrow for x axis# axis.line.x = element_line(arrow = arrow(# ends = "last",# type = "closed",# length = unit(0.25, "npc"))),# # add arrow for y axis# axis.line.y = element_line(arrow = arrow(# ends = "first",# type = "closed",# length = unit(0.25, "npc")))) })}# Run the application shinyApp(ui = ui, server = server)
Publish
ShinyProxy
within a quarto/rmarkdown document
Alternatives
Plotly/Highcharts
Observable
PowerBI/Tableau
References
Wickham, Hadley. 2021. Mastering Shiny: Build Interactive Apps, Reports, and Dashboards Powered by r. 1st edition. Sebastopol, CA: O’Reilly Media.